/**
  ******************************************************************************
  * @file    usbd_audio.c
  * @author  MCD Application Team
  * @brief   This file provides the Audio core functions.
  *
  * @verbatim
  *
  *          ===================================================================
  *                                AUDIO Class  Description
  *          ===================================================================
  *           This driver manages the Audio Class 1.0 following the "USB Device Class Definition for
  *           Audio Devices V1.0 Mar 18, 98".
  *           This driver implements the following aspects of the specification:
  *             - Device descriptor management
  *             - Configuration descriptor management
  *             - Standard AC Interface Descriptor management
  *             - 1 Audio Streaming Interface (with single channel, PCM, Stereo mode)
  *             - 1 Audio Streaming Endpoint
  *             - 1 Audio Terminal Input (1 channel)
  *             - Audio Class-Specific AC Interfaces
  *             - Audio Class-Specific AS Interfaces
  *             - AudioControl Requests: only SET_CUR and GET_CUR requests are supported (for Mute)
  *             - Audio Feature Unit (limited to Mute control)
  *             - Audio Synchronization type: Asynchronous
  *             - Single fixed audio sampling rate (configurable in usbd_conf.h file)
  *          The current audio class version supports the following audio features:
  *             - Pulse Coded Modulation (PCM) format
  *             - sampling rate: 48KHz.
  *             - Bit resolution: 16
  *             - Number of channels: 2
  *             - No volume control
  *             - Mute/Unmute capability
  *             - Asynchronous Endpoints
  *
  * @note     In HS mode and when the DMA is used, all variables and data structures
  *           dealing with the DMA during the transaction process should be 32-bit aligned.
  *
  *
  *  @endverbatim
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2015 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                      www.st.com/SLA0044
  *
  ******************************************************************************
  */

/* BSPDependencies
- "stm32xxxxx_{eval}{discovery}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
- "stm32xxxxx_{eval}{discovery}_audio.c"
EndBSPDependencies */

/* Includes ------------------------------------------------------------------*/
#include "usbd_audio.h"
#include "usbd_ctlreq.h"


/** @addtogroup STM32_USB_DEVICE_LIBRARY
  * @{
  */


/** @defgroup USBD_AUDIO
  * @brief usbd core module
  * @{
  */

/** @defgroup USBD_AUDIO_Private_TypesDefinitions
  * @{
  */
/**
  * @}
  */


/** @defgroup USBD_AUDIO_Private_Defines
  * @{
  */
/**
  * @}
  */


/** @defgroup USBD_AUDIO_Private_Macros
  * @{
  */
#define AUDIO_SAMPLE_FREQ(frq)         (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))

#define AUDIO_PACKET_SZE(size)         (uint8_t)((size) & 0xFF), \
                                       (uint8_t)(((size) >> 8) & 0xFF)   

/**
  * @}
  */



int8_t muit_statusSpeak = 0;
int16_t CurrentVolumeSpeak = 0x0064;

int8_t muit_statusMicrophone = 0;
int16_t CurrentVolumeMicrophone = 0x064;

#define MAX_SPEAK_VOLUME 0x0064
#define MIN_SPEAK_VOLUME 0x0000
#define MAX_MIC_VOLUME 0x0064
#define MIN_MIC_VOLUME 0x0000   


/** @defgroup USBD_AUDIO_Private_FunctionPrototypes
  * @{
  */
static uint8_t USBD_AUDIO_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_AUDIO_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);

static uint8_t USBD_AUDIO_Setup(USBD_HandleTypeDef *pdev,
                                USBD_SetupReqTypedef *req);

static uint8_t *USBD_AUDIO_GetCfgDesc(uint16_t *length);
static uint8_t *USBD_AUDIO_GetDeviceQualifierDesc(uint16_t *length);
static uint8_t USBD_AUDIO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_AUDIO_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_AUDIO_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_AUDIO_EP0_TxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_AUDIO_SOF(USBD_HandleTypeDef *pdev);

static uint8_t USBD_AUDIO_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_AUDIO_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
static void AUDIO_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static void AUDIO_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static void AUDIO_REQ_GetMin(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static void AUDIO_REQ_GetMax(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static void AUDIO_REQ_GetRes(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);

/**
  * @}
  */

/** @defgroup USBD_AUDIO_Private_Variables
  * @{
  */

USBD_ClassTypeDef  USBD_AUDIO =
{
  USBD_AUDIO_Init,
  USBD_AUDIO_DeInit,
  USBD_AUDIO_Setup,
  USBD_AUDIO_EP0_TxReady,
  USBD_AUDIO_EP0_RxReady,
  USBD_AUDIO_DataIn,
  USBD_AUDIO_DataOut,
  USBD_AUDIO_SOF,
  USBD_AUDIO_IsoINIncomplete,
  USBD_AUDIO_IsoOutIncomplete,
  USBD_AUDIO_GetCfgDesc,
  USBD_AUDIO_GetCfgDesc,
  USBD_AUDIO_GetCfgDesc,
  USBD_AUDIO_GetDeviceQualifierDesc,
};

/* USB AUDIO device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_AUDIO_CfgDesc[USB_AUDIO_CONFIG_DESC_SIZ] __ALIGN_END =
{
	/* Configuration 1 */
	0x09,                                 /* bLength */
	USB_DESC_TYPE_CONFIGURATION,          /* bDescriptorType */
	LOBYTE(USB_AUDIO_CONFIG_DESC_SIZ),    /* wTotalLength  109 bytes*/
	HIBYTE(USB_AUDIO_CONFIG_DESC_SIZ),       
	0x04,    //NumInterfaces:4                 
	0x01,    //ConfigurationValue               
	0x00,    //Configuration String             
	0x80,    //Attributes:Bus Power             
	0x32,    //MaxPower = 0xfa*2ma  
    
    /**********************Audio Interface Descriptor(No.0):0x04**********************/
    0x09,    //Length                    
    0x04,    //DescriptorType:Inerface   
    0x00,    //InterfaceNum:0            
    0x00,    //AlternateSetting:0        
    0x00,    //NumEndpoint:0             
    0x01,    //InterfaceClass:audio      
    0x01,    //InterfaceSubClass:audio ctl
    0x00,    //InterfaceProtocol         
    0x00,    //Interface String       
    
    /*******************AC Header of Interface Descriptor:0x24 0x01*************************/  
    0x0a,    //Length                                                                                       
    0x24,    //DescriptorType:audio interface descriptor                                                    
    0x01,    //DescriptorSubType:audio control header                                                       
    0x00,
    0x01,    //bcdADC:audio Device Class v1.00                                                              
    0x48,    
    0x00,    //TotalLength:0x0048                                                                           
    0x02,    //InCollection:2 AudioStreaming interface                                                      
    0x01,    //InterfaceNr(2) - AS #1 id AudioStreaming interface 2 belongs to this AudioControl interface  
    0x02,    //InterfaceNr(1) - AS #2 id AudioStreaming interface 1 belongs to this AudioControl interface  
    
    
    /******************* AC Specific type of Input Terminal:0x24 0x02*************************/  
    0x0c,    //Length                                                                                                   
    0x24,    //DescriptorType:audio interface descriptor                                                                
    0x02,    //DescriptorSubType:Input Terminal                                                                         
    0x01,    //TerminalID:0x01                                                                                          
    0x01,
    0x02,    //TerminalType:USB Microphone                                                                               
    0x00,    //AssocTerminal                                                                                            
    0x02,    //NrChannels:2 channel                                                                                            
    0x03,    
    0x00,    //ChannelConfig:Left Front,Right Front, 
    0x00,    //ChannelName String                                                                                       
    0x00,    //Terminal String               
    
    /*******************Audio Class Specific type of Feature Unit:0x24 0x06*************************/                                       
    0x0a,    //Length                                  
    0x24,    //DescriptorType:audio interface descriptor
    0x06,    //DescriptorSubType:Audio Feature Unit    
    0x02,    //UnitID:0x02                             
    0x01,    //SourceID:1 #Microphone IT               
    0x01,    //ControlSize:1 byte                      
    0x01,    //Controls:Mute                          
    0x02,    //Controls(0):Volume                      
    0x02,    //Controls(1):Volume                      
    0x00,    //Feature String            
    
    /*******************Audio Class Specific type of Output Terminal:0x24 0x03*************************/        
    0x09,    //Length                                    
    0x24,    //DescriptorType:audio interface descriptor 
    0x03,    //DescriptorSubTYpe:Output Terminal         
    0x03,    //TerminalID:0x03                          
    0x01,
    0x01,    //TerminalType:USB Streaming                
    0x00,    //AssocTerminal:ID 0                        
    0x02,    //SourceID:2 #Feature UNIT   （ID 2作为控制microphone音量 - by ywj)                        
    0x00,    //Terminal String          
    
    /******************* Audio Class Specific type of Input Terminal:0x24 0x02*************************/  
    0x0c,    //Length                                   
    0x24,    //DescriptorType:audio interface descriptor
    0x02,    //DescriptorSubType:Input Terminal         
    0x04,    //TerminalID:0x04                          
    0x01,
    0x01,    //TerminalType:USB Streaming              
    0x00,    //AssocTerminal                            
    0x02,    //NrChannels:2 channel                             
    0x03,
    0x00,    //ChannelConfig:Left Front,Right Front,    
    0x00,    //ChannelName String                       
    0x00,    //Terminal String                          
    
    /*******************Audio Class Specific type of Feature Unit:0x24 0x06*************************/  
    0x0a,    //Length                                  
    0x24,    //DescriptorType:audio interface descriptor
    0x06,    //DescriptorSubType:Audio Feature Unit    
    0x05,    //UnitID:0x05                            
    0x04,    //SourceID:4 #USB Streaming IT               
    0x01,    //ControlSize:1 byte                      
    0x01,    //Controls:Mute,                    
    0x02,    //Controls(0):Volume                            
    0x02,    //Controls(1):Volume                            
    0x00,    //Feature String              
    
    /*******************Audio Class Specific type of Output Terminal:0x24 0x03*************************/    
    0x09,    //Length                                   
    0x24,    //DescriptorType:audio interface descriptor
    0x03,    //DescriptorSubTYpe:Output Terminal        
    0x06,    //TerminalID:0x06                          
    0x01,    
    0x03,    //TerminalType:Speaker               
    0x00,    //AssocTerminal:                      
    0x05,    //SourceID:5 #Feature UNIT   (ID 5作为控制speak音量 - by ywj)            
    0x00,    //Terminal String

    /******************************* Audio Control ENDPOINT descriptor: 0x05 *******************************/ 	   
	//控制端点描述符
    // 0x09, /* Size of this descriptor, in bytes: 9U */
    // 0x05,                /* ENDPOINT descriptor type */
    // 0x83,	//端点号
    // /* Endpoint address */
    // 0x03, //中断端点
    // 0x08, //端点包长度
	// 0x00, //端点包长度
    // 0x08, /* Interval */
    // 0, 0,


	/*****************Audio Recorder Interface descriptor(No.1):0x04***********************/  
	//录音部分
    0x09,    //Length                          
    0x04,    //DescriptorType:Interface        
    0x01,    //InterfaceNum:1                  
    0x00,    //AlternateSetting:0              
    0x00,    //NumEndpoint:0           
    0x01,    //InterfaceClass:audio            
    0x02,    //InterfaceSubClass:audio streaming
    0x00,    //InterfaceProtocol               
    0x00,    //Interface String            
    
	/*****************Audio Recorder Interface descriptor(No.1):0x04***********************/  	    
    0x09,    //Length                          
    0x04,    //DescriptorType:Interface        
    0x01,    //InterfaceNum:1                  
    0x01,    //AlternateSetting:1              
    0x01,    //NumEndpoint:1                   
    0x01,    //InterfaceClass:audio            
    0x02,    //InterfaceSubClass:audio streaming
    0x00,    //InterfaceProtocol               
    0x00,    //Interface String        
    
	/*******************AS descriptor subtype Descriptor:0x24 0x01*************************/    
    0x07,    //Length                                     
    0x24,    //DescriptorType:audio interface descriptor  
    0x01,    //DescriptorSubType:AS_GENERAL               
    0x03,    //TerminalLink:#3USB USB Streaming OT          
    0x00,    //Delay:0                                    
    0x01,
    0x00,    //FormatTag:PCM        
    
   /****************** Audio Class Specific type I format INTERFACE Descriptor: 0x24 0X02 ***********/ 
   //设置音频流的格式
    0x0b,    //Length                                  
    0x24,    //DescriptorType:audio interface descriptor
    0x02,    //DescriptorSubType:Format_type           
    0x01,    //FormatType:Format type 1                
    0x02,    //NumberOfChanne:2                        
    0x03,    //SubframeSize:2byte                      
    24,    //BitsResolution:16bit                    
    0x01,    //SampleFreqType:One sampling frequency.   
	AUDIO_SAMPLE_FREQ(USBD_AUDIO_FREQ),                   
    
    /******************************* Audio Recorder IN ENDPOINT descriptor: 0x05 *******************************/
    0x09,    //Length                                                            
    0x05,    //DescriptorType:endpoint descriptor                                
    AUDIO_IN_EP,    //EndpointAddress:Input endpoint 2                             
    // 0x01 | 0x04 | (0x2 << 4U),	//苹果设备使用隐式反馈
	0x01 | 0x04,					//苹果设备也使用feedback
	AUDIO_PACKET_SZE(AUDIO_OUT_PACKET),                                     
    0x01,    //Interval    
    0x00,
    0x00,                                 
    
    /******************************* Audio Class Specific ENDPOINT Descriptor: 0x25 0x01*******************************/   
    0x07,    //Length                                   
    0x25,    //DescriptorType:audio endpoint descriptor 
    0x01,    //DescriptorSubType:audio endpiont general 
    0x00,    //Attributes:0x00........             
    0x00,    //LockDelayUnits                           
    0x00,
    0x00,    //LockDelay                         
    
    /***********************Audio Speaker Interface descriptor(No.2):0x04*****************************/  	
	//播放部分开始
    0x09,    //Length                          
    0x04,    //DescriptorType:Interface        
    0x02,    //InterfaceNum:2                  
    0x00,    //AlternateSetting:0              
    0x00,    //NumEndpoint:0                   
    0x01,    //InterfaceClass:audio            
    0x02,    //InterfaceSubClass:audio streaming
    0x00,    //InterfaceProtocol               
    0x00,    //Interface String                
    
    /***********************Audio Speaker Interface descriptor(No.2):0x04*****************************/  	
    0x09,    //Length                          
    0x04,    //DescriptorType:Interface        
    0x02,    //InterfaceNum:2                  
    0x01,    //AlternateSetting:1              
    0x02,    //NumEndpoint:2         	//这里包括一个反馈端点          
    0x01,    //InterfaceClass:audio            
    0x02,    //InterfaceSubClass:audio streaming
    0x00,    //InterfaceProtocol               
    0x00,    //Interface String                
    
    /*******************AS_GENERAL descriptor subtype Descriptor:0x24 0x01*************************/  
    0x07,    //Length                                  
    0x24,    //DescriptorType:audio interface descriptor
    0x01,    //DescriptorSubType:AS_GENERAL            
    0x04,    //TerminalLink:#4 USB Streaming IT    
    0x01,    //Delay:1                                 
    0x01,
    0x00,    //FormatTag:PCM     
    
    /****************** Audio Class Specific type I format INTERFACE Descriptor: 0x24 0X02 ***********/   
    0x0b,    //Length                                  
    0x24,    //DescriptorType:audio interface descriptor
    0x02,    //DescriptorSubType:Format_type           
    0x01,    //FormatType:Format type 1                
    0x02,    //NumberOfChanne:1                        
    0x03,    //SubframeSize:3byte                      
    24,    //BitsResolution:24bit                    
    0x01,    //SampleFreqType:One sampling frequency.  
	AUDIO_SAMPLE_FREQ(USBD_AUDIO_FREQ),          
    
    /******************************* Audio Speaker OUT ENDPOINT descriptor: 0x05 *******************************/ 
	//播放端点描述符	
    0x09,    //Length                                                               
    0x05,    //DescriptorType:endpoint descriptor                                   
    AUDIO_OUT_EP,    //EndpointAddress:Output endpoint 01                                   
    0x01 | 0x04,    //Attributes:0x05,Isochronous,Synchronization Type(Asynchronous).........	
    AUDIO_PACKET_SZE(AUDIO_OUT_PACKET),                                          
    0x01,    //Interval       AUDIO_OUT_PACKET      
    0x00,
    0x81,            
    
    /******************************* Audio Class Specific ENDPOINT Descriptor: 0x25 0x01*******************************/  
    0x07,    //Length                                    
    0x25,    //DescriptorType:audio endpoint descriptor  
    0x01,    //DescriptorSubType:audio endpiont general  
    0x00,    //Attributes:0x00.............              
    0x00,    //LockDelayUnits                            
    0x00,
    0x00,    //LockDelay  

        //反馈端点描述符
    /******************************* Audio feedback IN ENDPOINT descriptor: 0x05 *******************************/
    0x09, /* bLength */
    0x05,         /* bDescriptorType */
    AUDIO_FEEDBACK_EP,
    0x01 | 0x04 | 0x10,         /*  Types -
                                Transfer: ISOCHRONOUS
                                Sync: Async
                                Usage: Feedback EP   */
    0x03,   /* wMaxPacketSize */
    0x00, /* wMaxPacketSize */
    0x01, /* interval polling(2^x ms) */
    0x06,
    0x00,
#if 1
	//************************************************************************************************************
	//HID 描述符
	// Interface Descriptor:
	// ------------------------------
	0x09,	//bLength
	0x04,	//bDescriptorType
	0x03,	//bInterfaceNumber
	0x00,	//bAlternateSetting
	0x02,	//bNumEndPoints
	0x03,	//bInterfaceClass      (Human Interface Device Class)
	0x00,	//bInterfaceSubClass   
	0x00,	//bInterfaceProtocol   
	0x00,	//iInterface

	// HID Descriptor:
	// ------------------------------
	0x09,	//bLength
	0x21,	//bDescriptorType
	0x10,	//bcdHID
	0x01,
	0x00,	//bCountryCode
	0x01,	//bNumDescriptors
	0x22,	//bDescriptorType   (Report descriptor)
	HID_MOUSE_REPORT_DESC_SIZE,	//bDescriptorLength
	0x00,

	// Endpoint Descriptor:
	// ------------------------------
	0x07,	//bLength
	0x05,	//bDescriptorType
	HID_IN_EP,	//bEndpointAddress  (IN endpoint 1)
	0x03,	//bmAttributes      (Transfer: Interrupt / Synch: None / Usage: Data)
	0x40,	//wMaxPacketSize    (1 x 64 bytes)
	0x00,
	0x04,	//bInterval         (8 microframes)

	// Endpoint Descriptor:
	// ------------------------------
	0x07,	//bLength
	0x05,	//bDescriptorType
	HID_OUT_EP,	//bEndpointAddress  (OUT endpoint 2)
	0x03,	//bmAttributes      (Transfer: Interrupt / Synch: None / Usage: Data)
	0x40,	//wMaxPacketSize    (1 x 64 bytes)
	0x00,
	0x04,	//bInterval         (8 microframes)
	#endif

} ;

/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_AUDIO_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
  USB_LEN_DEV_QUALIFIER_DESC,
  USB_DESC_TYPE_DEVICE_QUALIFIER,
  0x00,
  0x02,
  0x00,
  0x00,
  0x00,
  0x40,
  0x01,
  0x00,
};

/*------------------------------------------------------------------------------------------------------------------
HID报告描述符
*/

__ALIGN_BEGIN uint8_t g_UsbDeviceHidReportDescriptor[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END = 
{
	//音量控制
	0x05, 0x0c, 					//UAGE_PAGE
	0x09, 0x01, 					//UAGE
	0xa1, 0x01,						//COLLECTION
	0x15, 0x00, 					//LOGICAL_MINIMUM
	0x25, 0x01,						//LOGICAL_MAXIMUM
	0x09, 0xCD, 					//UAGE - Play/Pause
	0x09, 0xb5, 					//UAGE - Scan Next Track
	0x09, 0xb6, 					//UAGE - Scan Previous Track
	0x09, 0xe9, 					//UAGE - Volume Increment
	0x09, 0xea, 					//UAGE - Volume Decrement
	0x09, 0xe2,						//UAGE - Mute 
	0x09, 0xb1, 					//UAGE - Pause
	0x09, 0xb7, 					//UAGE - Stop
	0x75, 0x01, 					//REPORT_SIZE
	0x95, 0x08,						//REPORT_COUNT
	0x81, 0x02, 					//INPUT(Data,Var,Abs)
	0xc0,							//END_COLLECTION
};


uint8_t audioFeedBackBuffer[4] = {0x40,0x06,0x0b};     /*该设备为：44.1K采样率，10.14格式*/

void SetFeedBackSampleRate(uint32_t Rata)
{
	Rata = (Rata * 16384) / 1000;
	audioFeedBackBuffer[0] = Rata;
	audioFeedBackBuffer[1] = Rata>>8;
	audioFeedBackBuffer[2] = Rata>>16;
}
/**
  * @}
  */

/** @defgroup USBD_AUDIO_Private_Functions
  * @{
  */

/**
  * @brief  USBD_AUDIO_Init
  *         Initialize the AUDIO interface
  * @param  pdev: device instance
  * @param  cfgidx: Configuration index
  * @retval status
  */
 USBD_AUDIO_HandleTypeDef USBD_Audio_Handle;

 uint32_t CurrentSampleRate = 48020;
 uint8_t dump_buffer[500];

 uint8_t RxdataBuffer[500];


 uint8_t HID_RxBuffer[64];


static uint8_t  USBD_AUDIO_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
  USBD_AUDIO_HandleTypeDef   *haudio;

	/* Open EP OUT */
	USBD_LL_OpenEP(pdev, AUDIO_OUT_EP, USBD_EP_TYPE_ISOC, AUDIO_OUT_PACKET);
	USBD_LL_OpenEP(pdev, AUDIO_IN_EP, USBD_EP_TYPE_ISOC, AUDIO_OUT_PACKET);
	USBD_LL_OpenEP(pdev, AUDIO_FEEDBACK_EP, USBD_EP_TYPE_ISOC, 0X03);
	USBD_LL_OpenEP(pdev, HID_OUT_EP, USBD_EP_TYPE_INTR, 64);
	USBD_LL_OpenEP(pdev, HID_IN_EP, USBD_EP_TYPE_INTR, 64);

	pdev->ep_out[AUDIO_OUT_EP & 0xFU].is_used = 1U;
	pdev->ep_in[AUDIO_IN_EP & 0xFU].is_used = 1U;
	pdev->ep_in[AUDIO_FEEDBACK_EP & 0xFU].is_used = 1U;
	pdev->ep_out[HID_OUT_EP & 0xFU].is_used = 1U;
	pdev->ep_in[HID_IN_EP & 0xFU].is_used = 1U;

  /* Allocate Audio structure */
  //pdev->pClassData = USBD_malloc(sizeof(USBD_AUDIO_HandleTypeDef));
  USBD_Audio_Handle.AudioStatus = 0;
  USBD_Audio_Handle.RecordStatus = 0;
  pdev->pClassData = &USBD_Audio_Handle;

  if (pdev->pClassData == NULL)
  {
    return USBD_FAIL;
  }
  else
  {
    haudio = (USBD_AUDIO_HandleTypeDef *) pdev->pClassData;
    haudio->alt_setting = 0U;
    haudio->offset = AUDIO_OFFSET_UNKNOWN;
    haudio->wr_ptr = 0U;
    haudio->rd_ptr = 0U;
    haudio->rd_enable = 0U;

    /* Initialize the Audio output Hardware layer */
    if (((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->Init(USBD_AUDIO_FREQ,
                                                         AUDIO_DEFAULT_VOLUME,
                                                         0U) != 0)
    {
      return USBD_FAIL;
    }

    /* Prepare Out endpoint to receive 1st packet */
    //USBD_LL_PrepareReceive(pdev, AUDIO_OUT_EP, haudio->buffer,AUDIO_OUT_PACKET);

	USBD_LL_PrepareReceive(pdev, HID_OUT_EP, HID_RxBuffer,64);

  }

  return USBD_OK;
}

/**
  * @brief  USBD_AUDIO_Init
  *         DeInitialize the AUDIO layer
  * @param  pdev: device instance
  * @param  cfgidx: Configuration index
  * @retval status
  */
static uint8_t  USBD_AUDIO_DeInit(USBD_HandleTypeDef *pdev,
                                  uint8_t cfgidx)
{
	/* Open EP OUT */
	USBD_LL_CloseEP(pdev, AUDIO_OUT_EP);
	USBD_LL_CloseEP(pdev, AUDIO_IN_EP);
	USBD_LL_CloseEP(pdev, AUDIO_FEEDBACK_EP);
	USBD_LL_CloseEP(pdev, HID_OUT_EP);
	USBD_LL_CloseEP(pdev, HID_IN_EP);

	pdev->ep_out[AUDIO_OUT_EP & 0xFU].is_used = 0U;
	pdev->ep_in[AUDIO_IN_EP & 0xFU].is_used = 0U;
	pdev->ep_in[AUDIO_FEEDBACK_EP & 0xFU].is_used = 0U;
	pdev->ep_out[HID_OUT_EP & 0xFU].is_used = 0U;
	pdev->ep_in[HID_IN_EP & 0xFU].is_used = 0U;

  /* DeInit  physical Interface components */
  if (pdev->pClassData != NULL)
  {
    ((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->DeInit(0U);
    //USBD_free(pdev->pClassData); //之前没有申请，所以不能释放
    pdev->pClassData = NULL;
  }

  return USBD_OK;
}

/**
  * @brief  USBD_AUDIO_Setup
  *         Handle the AUDIO specific requests
  * @param  pdev: instance
  * @param  req: usb requests
  * @retval status
  */
static uint8_t  USBD_AUDIO_Setup(USBD_HandleTypeDef *pdev,
                                 USBD_SetupReqTypedef *req)
{
  USBD_AUDIO_HandleTypeDef *haudio;
  uint16_t len;
  uint8_t *pbuf;
  uint16_t status_info = 0U;
  uint8_t ret = USBD_OK;

  haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassData;

  switch (req->bmRequest & USB_REQ_TYPE_MASK)
  {
    case USB_REQ_TYPE_CLASS :
      switch (req->bRequest)
      {
		case AUDIO_REQ_GET_CUR:
			AUDIO_REQ_GetCurrent(pdev, req);
		break;
		case AUDIO_REQ_SET_CUR:
			AUDIO_REQ_SetCurrent(pdev, req);   
		break;
		case AUDIO_REQ_GET_MIN: 
			AUDIO_REQ_GetMin(pdev, req);
		break;
		case AUDIO_REQ_GET_MAX: 
			AUDIO_REQ_GetMax(pdev, req);
		break;
		case AUDIO_REQ_GET_RES: 
			AUDIO_REQ_GetRes(pdev, req);
		break; 

		//HID SET IDEL
		case 0x0A: 
			ret = USBD_OK;
		break;

        default:
          USBD_CtlError(pdev, req);
          ret = USBD_FAIL;
          break;
      }
      break;

    case USB_REQ_TYPE_STANDARD:
      switch (req->bRequest)
      {
        case USB_REQ_GET_STATUS:
          if (pdev->dev_state == USBD_STATE_CONFIGURED)
          {
            USBD_CtlSendData(pdev, (uint8_t *)(void *)&status_info, 2U);
          }
          else
          {
            USBD_CtlError(pdev, req);
            ret = USBD_FAIL;
          }
          break;

        case USB_REQ_GET_DESCRIPTOR:
          if ((req->wValue >> 8) == AUDIO_DESCRIPTOR_TYPE)
          {
            pbuf = USBD_AUDIO_CfgDesc + 18;
            len = MIN(USB_AUDIO_DESC_SIZ, req->wLength);

            USBD_CtlSendData(pdev, pbuf, len);
          }
		  //HID 报告描述符
		  else if ((req->wValue >> 8) == 0x22)
		  {
			pbuf = g_UsbDeviceHidReportDescriptor;
            len = MIN(HID_MOUSE_REPORT_DESC_SIZE, req->wLength);
            USBD_CtlSendData(pdev, pbuf, len);
		  }
          break;

        case USB_REQ_GET_INTERFACE :
          if (pdev->dev_state == USBD_STATE_CONFIGURED)
          {
            USBD_CtlSendData(pdev, (uint8_t *)(void *)&haudio->alt_setting, 1U);
          }
          else
          {
            USBD_CtlError(pdev, req);
            ret = USBD_FAIL;
          }
          break;

        case USB_REQ_SET_INTERFACE :
          if (pdev->dev_state == USBD_STATE_CONFIGURED)
          {
            if ((uint8_t)(req->wValue) <= USBD_MAX_NUM_INTERFACES)
            {
              	haudio->alt_setting = (uint8_t)(req->wValue);
				if((req->wIndex == 2)&&(req->wValue == 1))//如果选择了interface 2 alt 1，开始播放
				{
					//开始播放
					haudio->AudioStatus = 1;
                    USBD_LL_PrepareReceive(pdev, AUDIO_OUT_EP, RxdataBuffer ,300);


                    // SetFeedBackSampleRate(48000);
                    // HAL_PCD_EP_Flush(pdev->pData, AUDIO_FEEDBACK_EP);
                    // HAL_PCD_EP_Transmit(pdev->pData,AUDIO_FEEDBACK_EP,(uint8_t *)&audioFeedBackBuffer[0],3);
  
				}
				else if((req->wIndex == 2)&&(req->wValue == 0))//如果选择了interface 2 alt 0，结束播放
				{
					//停止播放
					haudio->AudioStatus = 0;
  
				}
				else if((req->wIndex == 1)&&(req->wValue == 1))//如果选择了interface 1 alt 1，录音
				{
					//开始录音
					haudio->RecordStatus = 1;
					HAL_PCD_EP_Flush(pdev->pData, AUDIO_IN_EP);
					HAL_PCD_EP_Transmit(pdev->pData,AUDIO_IN_EP,(uint8_t *)&dump_buffer[0],288);
				}
				else if((req->wIndex == 1)&&(req->wValue == 0))//如果选择了interface 1 alt 0，停止录音
				{
					//关闭录音
					haudio->RecordStatus = 0;
				}
            }
            else
            {
              /* Call the error management function (command will be nacked */
              USBD_CtlError(pdev, req);
              ret = USBD_FAIL;
            }
          }
          else
          {
            USBD_CtlError(pdev, req);
            ret = USBD_FAIL;
          }
          break;

        default:
          USBD_CtlError(pdev, req);
          ret = USBD_FAIL;
          break;
      }
      break;
    default:
      USBD_CtlError(pdev, req);
      ret = USBD_FAIL;
      break;
  }

  return ret;
}


/**
  * @brief  USBD_AUDIO_GetCfgDesc
  *         return configuration descriptor
  * @param  speed : current device speed
  * @param  length : pointer data length
  * @retval pointer to descriptor buffer
  */
static uint8_t  *USBD_AUDIO_GetCfgDesc(uint16_t *length)
{
  *length = sizeof(USBD_AUDIO_CfgDesc);

  return USBD_AUDIO_CfgDesc;
}


typedef enum
{
  HID_IDLE = 0,
  HID_BUSY,
}
HID_StateTypeDef;

HID_StateTypeDef hid_status = HID_IDLE;


/**
  * @brief  USBD_AUDIO_DataIn
  *         handle data IN Stage
  * @param  pdev: device instance
  * @param  epnum: endpoint index
  * @retval status
  */
 uint32_t FeedBackTime = 0;
 uint32_t FeedBackFinish = 1;
 uint32_t Send_INT_Count = 0;

 extern void xAPP_SendAudioDataFinishCallBack(uint8_t* Buffer , uint32_t* Len);

static uint8_t  USBD_AUDIO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{

	//录音端点
	if(epnum == 2)
	{
        uint32_t Len; 
        Send_INT_Count++;
		HAL_PCD_EP_Flush(pdev->pData, AUDIO_IN_EP);
        xAPP_SendAudioDataFinishCallBack(dump_buffer , &Len);
		HAL_PCD_EP_Transmit(pdev->pData,AUDIO_IN_EP,(uint8_t *)&dump_buffer[0] ,Len);
	}
	//反馈端点
	if(epnum == 1)
	{
        FeedBackTime++;
        FeedBackFinish = 1;

	}

	//HID IN端点
	if(epnum == 3)
	{
		hid_status = HID_IDLE;
	}
  /* Only OUT data are processed */
  return USBD_OK;
}

static uint8_t SendBuffer[64];

uint8_t USBD_HID_SendReport(USBD_HandleTypeDef  *pdev,uint8_t *report,uint16_t len)
{
	if (pdev->dev_state == USBD_STATE_CONFIGURED)
	{
		if (hid_status == HID_IDLE)
		{
			hid_status = HID_BUSY;
			memcpy(SendBuffer ,report , len );

			// HAL_PCD_EP_Flush(pdev->pData, HID_IN_EP);
			// HAL_PCD_EP_Transmit(pdev->pData,HID_IN_EP,SendBuffer,len);

			USBD_LL_Transmit(pdev, HID_IN_EP, SendBuffer, len);
		}
		else
		{
			return USBD_BUSY;
		}
	}
	return USBD_OK;
}


extern USBD_HandleTypeDef hUsbDeviceFS;
uint8_t USBD_HID_SendReport_MY(uint8_t *report,uint16_t len)
{
	return USBD_HID_SendReport(&hUsbDeviceFS,report,len);
}

void USBD_Audio_SendFeedback(void)
{
	if (hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED)
	{
		SetFeedBackSampleRate(CurrentSampleRate);
		HAL_PCD_EP_Flush(hUsbDeviceFS.pData, AUDIO_FEEDBACK_EP);
		HAL_PCD_EP_Transmit(hUsbDeviceFS.pData,AUDIO_FEEDBACK_EP,(uint8_t *)&audioFeedBackBuffer[0],3);
	}
}

/**
  * @brief  USBD_AUDIO_EP0_RxReady
  *         handle EP0 Rx Ready event
  * @param  pdev: device instance
  * @retval status
  */
static uint8_t  USBD_AUDIO_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
  USBD_AUDIO_HandleTypeDef   *haudio;
  haudio = (USBD_AUDIO_HandleTypeDef *) pdev->pClassData;

  if (haudio->control.cmd == AUDIO_REQ_SET_CUR)
  {
		//播放音量设置
		if(haudio->control.unit == 0x05)
		{
			if(haudio->control.len == 1)
			{
			muit_statusSpeak = haudio->control.data[0];
			}
			else if(haudio->control.len == 2)
			{
				CurrentVolumeSpeak = haudio->control.data[1];
				CurrentVolumeSpeak <<= 8;
				CurrentVolumeSpeak |= haudio->control.data[0];

			}
		}
		if(haudio->control.unit == 0x02)
		{
			if(haudio->control.len == 1)
			{
				muit_statusMicrophone = haudio->control.data[0];
			}
			else if(haudio->control.len == 2)
			{
				CurrentVolumeMicrophone = haudio->control.data[1];
				CurrentVolumeMicrophone <<= 8;
				CurrentVolumeMicrophone |= haudio->control.data[0];
			}
		}


		if (haudio->control.unit == AUDIO_OUT_STREAMING_CTRL)
		{
			((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->MuteCtl(haudio->control.data[0]);
			haudio->control.cmd = 0U;
			haudio->control.len = 0U;
		}
	}

	return USBD_OK;
}
/**
  * @brief  USBD_AUDIO_EP0_TxReady
  *         handle EP0 TRx Ready event
  * @param  pdev: device instance
  * @retval status
  */
static uint8_t  USBD_AUDIO_EP0_TxReady(USBD_HandleTypeDef *pdev)
{
  /* Only OUT control data are processed */
  return USBD_OK;
}
/**
  * @brief  USBD_AUDIO_SOF
  *         handle SOF event
  * @param  pdev: device instance
  * @retval status
  */
static uint8_t  USBD_AUDIO_SOF(USBD_HandleTypeDef *pdev)
{
  return USBD_OK;
}

/**
  * @brief  USBD_AUDIO_SOF
  *         handle SOF event
  * @param  pdev: device instance
  * @retval status
  */
void  USBD_AUDIO_Sync(USBD_HandleTypeDef *pdev, AUDIO_OffsetTypeDef offset)
{
  uint32_t cmd = 0U;
  USBD_AUDIO_HandleTypeDef   *haudio;
  haudio = (USBD_AUDIO_HandleTypeDef *) pdev->pClassData;

  haudio->offset =  offset;

  if (haudio->rd_enable == 1U)
  {
    haudio->rd_ptr += (uint16_t)(AUDIO_TOTAL_BUF_SIZE / 2U);

    if (haudio->rd_ptr == AUDIO_TOTAL_BUF_SIZE)
    {
      /* roll back */
      haudio->rd_ptr = 0U;
    }
  }

  if (haudio->rd_ptr > haudio->wr_ptr)
  {
    if ((haudio->rd_ptr - haudio->wr_ptr) < AUDIO_OUT_PACKET)
    {
      cmd = AUDIO_TOTAL_BUF_SIZE / 2U + 4U;
    }
    else
    {
      if ((haudio->rd_ptr - haudio->wr_ptr) > (AUDIO_TOTAL_BUF_SIZE - AUDIO_OUT_PACKET))
      {
        cmd = AUDIO_TOTAL_BUF_SIZE / 2U - 4U;
      }
    }
  }
  else
  {
    if ((haudio->wr_ptr - haudio->rd_ptr) < AUDIO_OUT_PACKET)
    {
      cmd = AUDIO_TOTAL_BUF_SIZE / 2U - 4U;
    }
    else
    {
      if ((haudio->wr_ptr - haudio->rd_ptr) > (AUDIO_TOTAL_BUF_SIZE - AUDIO_OUT_PACKET))
      {
        cmd = AUDIO_TOTAL_BUF_SIZE / 2U + 4U;
      }
    }
  }

  if (haudio->offset == AUDIO_OFFSET_FULL)
  {
    ((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->AudioCmd(&haudio->buffer[0],
                                                         cmd,
                                                         AUDIO_CMD_PLAY);
    haudio->offset = AUDIO_OFFSET_NONE;
  }
}

/**
  * @brief  USBD_AUDIO_IsoINIncomplete
  *         handle data ISO IN Incomplete event
  * @param  pdev: device instance
  * @param  epnum: endpoint index
  * @retval status
  */
static uint8_t  USBD_AUDIO_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
  return USBD_OK;
}
/**
  * @brief  USBD_AUDIO_IsoOutIncomplete
  *         handle data ISO OUT Incomplete event
  * @param  pdev: device instance
  * @param  epnum: endpoint index
  * @retval status
  */
static uint8_t  USBD_AUDIO_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
  return USBD_OK;
}
/**
  * @brief  USBD_AUDIO_DataOut
  *         handle data OUT Stage
  * @param  pdev: device instance
  * @param  epnum: endpoint index
  * @retval status
  */
uint32_t AudioReceiveCount;

uint8_t RxdataBufferB[300];
uint32_t INT_Count;


extern void xAPP_ReceiveAudioDataCallBack(uint8_t* Buffer , uint32_t Len);
static uint8_t  USBD_AUDIO_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{

	if (epnum == AUDIO_OUT_EP)
	{

		INT_Count++;
		AudioReceiveCount = HAL_PCD_EP_GetRxCount(pdev->pData,AUDIO_OUT_EP);	

		xAPP_ReceiveAudioDataCallBack(RxdataBuffer , AudioReceiveCount);
		
		USBD_LL_PrepareReceive(pdev, AUDIO_OUT_EP, RxdataBuffer ,500);
	}

	if (epnum == HID_OUT_EP)
	{
		USBD_LL_PrepareReceive(pdev, HID_OUT_EP, HID_RxBuffer,64);
	}

	return USBD_OK;
}





/**
  * @brief  AUDIO_Req_GetCurrent
  *         Handles the GET_CUR Audio control request.
  * @param  pdev: instance
  * @param  req: setup class request
  * @retval status
  */
static void AUDIO_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{  
  USBD_AUDIO_HandleTypeDef   *haudio;
  haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;
	
		//speak
	if((req->wIndex >> 8) == 0x05)
	{
		if(req->wLength == 0x01)
		{
			//静音查询
			haudio->control.data[0] = muit_statusSpeak;
			USBD_CtlSendData (pdev, haudio->control.data,req->wLength);
		}

		if(req->wLength == 0x02)
		{
			/* Send the current mute state */
			//查询当前音量
			haudio->control.data[1] = CurrentVolumeSpeak>>8;
			haudio->control.data[0] = CurrentVolumeSpeak;
			USBD_CtlSendData (pdev, haudio->control.data,req->wLength);
		}

	}
	//microphone
	else if((req->wIndex >> 8) == 0x02)
	{
		if(req->wLength == 0x01)
		{
			//静音查询
			haudio->control.data[0] = muit_statusMicrophone;
			USBD_CtlSendData (pdev, haudio->control.data,req->wLength);
		}

		if(req->wLength == 0x02)
		{
			/* Send the current mute state */
			//查询当前音量
			haudio->control.data[1] = CurrentVolumeMicrophone>>8;
			haudio->control.data[0] = CurrentVolumeMicrophone;
			USBD_CtlSendData (pdev, haudio->control.data,req->wLength);
		}
	}
}


/**
  * @brief  AUDIO_Req_SetCurrent
  *         Handles the SET_CUR Audio control request.
  * @param  pdev: instance
  * @param  req: setup class request
  * @retval status
  */
static void AUDIO_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{ 
	USBD_AUDIO_HandleTypeDef   *haudio;
	haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;

	USBD_CtlPrepareRx (pdev,haudio->control.data,req->wLength);   
	haudio->control.cmd = AUDIO_REQ_SET_CUR;     /* Set the request value */
	haudio->control.len = req->wLength;          /* Set the request data length */
	haudio->control.unit = HIBYTE(req->wIndex);  /* Set the request target unit */
}



static void AUDIO_REQ_GetMin(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{  
  USBD_AUDIO_HandleTypeDef   *haudio;
  haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;
  	

	
			//speak
			if((req->wIndex & 0xFF00) == 0x0500)
			{
				if(req->wLength == 0x02)
				{
					//查询最小音量 - 0dB
					haudio->control.data[1] = (uint8_t)(MIN_SPEAK_VOLUME>>8);
					haudio->control.data[0] = (uint8_t)MIN_SPEAK_VOLUME;
					USBD_CtlSendData (pdev, haudio->control.data,req->wLength);
				}
			}
			//microphone
			if((req->wIndex & 0xFF00) == 0x0200)
			{
				if(req->wLength == 0x02)
				{
					haudio->control.data[1] = (uint8_t)(MIN_MIC_VOLUME>>8);
					haudio->control.data[0] = (uint8_t)MIN_MIC_VOLUME;
					USBD_CtlSendData (pdev, haudio->control.data,req->wLength);
				}
			}

}

static void AUDIO_REQ_GetMax(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{  
  USBD_AUDIO_HandleTypeDef   *haudio;
  haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;
  	
			//speak
			if((req->wIndex & 0xFF00) == 0x0500)
			{
				if(req->wLength == 0x02)
				{
					haudio->control.data[1] = (uint8_t)(MAX_SPEAK_VOLUME>>8);
					haudio->control.data[0] = (uint8_t)(MAX_SPEAK_VOLUME);
					USBD_CtlSendData (pdev, haudio->control.data,req->wLength);
				}
			}
			//microphone
			if((req->wIndex & 0xFF00) == 0x0200)
			{
				if(req->wLength == 0x02)
				{
					haudio->control.data[1] = (uint8_t)(MAX_MIC_VOLUME>>8);
					haudio->control.data[0] = (uint8_t)(MAX_MIC_VOLUME);
					USBD_CtlSendData (pdev, haudio->control.data,req->wLength);
				}
			}

}


static void AUDIO_REQ_GetRes(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
	USBD_AUDIO_HandleTypeDef   *haudio;
	haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;

	if(req->wLength == 0x02)
	{
		//读取装置音量变化单位
		haudio->control.data[1] = 0x00;
		haudio->control.data[0] = 0x01;
		USBD_CtlSendData (pdev, haudio->control.data,req->wLength);
	}

}


/**
* @brief  DeviceQualifierDescriptor
*         return Device Qualifier descriptor
* @param  length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t  *USBD_AUDIO_GetDeviceQualifierDesc(uint16_t *length)
{
  *length = sizeof(USBD_AUDIO_DeviceQualifierDesc);

  return USBD_AUDIO_DeviceQualifierDesc;
}

/**
* @brief  USBD_AUDIO_RegisterInterface
* @param  fops: Audio interface callback
* @retval status
*/
uint8_t  USBD_AUDIO_RegisterInterface(USBD_HandleTypeDef *pdev,
                                      USBD_AUDIO_ItfTypeDef *fops)
{
  if (fops != NULL)
  {
    pdev->pUserData = fops;
  }

  return USBD_OK;
}
/**
  * @}
  */


/**
  * @}
  */


/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
